home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CBASE102.ARJ / BUOPS.C < prev    next >
Text File  |  1991-09-23  |  15KB  |  624 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)buops.c    1.5 - 91/09/23" */
  5.  
  6. #include <ansi.h>
  7.  
  8. /* ansi headers */
  9. #include <errno.h>
  10. #ifdef AC_STRING
  11. #include <string.h>
  12. #endif
  13.  
  14. /* local headers */
  15. #include "blkio_.h"
  16.  
  17. /* check host definition */
  18. #ifndef OPSYS
  19. /*#error OPSYS macro not defined.*/
  20. #endif
  21. #if OPSYS < OS_AMIGADOS || OPSYS > OS_VMS
  22. /*#error Invalid OPSYS macro definition.*/
  23. #endif
  24.  
  25. /* system headers */
  26. #if OPSYS == OS_AMIGADOS    /* Amiga DOS =================================*/
  27.  
  28. #elif OPSYS == OS_DOS        /* DOS =======================================*/
  29. #if CCOM == CC_BC        /* Borland C++ -------------------------------*/
  30. #include <fcntl.h>        /* open() macro definitions */
  31. #include <io.h>            /* system call decls, lseek() macro defs */
  32. #include <share.h>        /* file sharing macros */
  33. #include <sys\types.h>
  34. #include <sys\stat.h>        /* file permission macros */
  35. #define MODE    (S_IREAD | S_IWRITE)
  36.                 /* file permissions for new files */
  37. #elif CCOM == CC_MSC || CCOM == CC_MSQC    /* Microsoft C or Quick C ------------*/
  38. #include <fcntl.h>        /* open() macro definitions */
  39. /*#include <io.h>        /* system call decls, lseek() macro defs */
  40. /* NOTE:  <io.h> not used for MSC because const qualifier missing from
  41.    sopen and write decls */
  42. #include <share.h>        /* file sharing macros */
  43. #include <sys\types.h>
  44. #include <sys\stat.h>        /* file permission macros */
  45. #ifdef AC_PROTO
  46. int    close(int fd);        /* system call declarations */
  47. long    lseek(int fd, long offset, int whence);
  48. int    sopen(const char *path, int oflag, ...);
  49. int    read(int fd, char *buf, unsigned n);
  50. int    write(int fd, const char *buf, unsigned n);
  51. #else
  52. int    close();
  53. long    lseek();
  54. int    sopen();
  55. int    read();
  56. int    write();
  57. #endif    /* #ifdef AC_PROTO */
  58. #define MODE    (S_IREAD | S_IWRITE)
  59.                 /* file permissions for new files */
  60. #endif    /* #if CCOM == CC_BC */
  61. #elif OPSYS == OS_MAC        /* Macintosh =================================*/
  62.  
  63. #elif OPSYS == OS_UNIX        /* UNIX ======================================*/
  64. #include <fcntl.h>        /* open() macro definitions */
  65. #include <unistd.h>        /* lseek() macro definitions */
  66. #include <sys/types.h>
  67. #include <sys/stat.h>        /* file permission macros */
  68. #ifdef AC_PROTO
  69. int    close(int fd);        /* system call declarations */
  70. long    lseek(int fd, long offset, int whence);
  71. int    open(const char *path, int flags, ...);
  72. int    read(int fd, char *buf, unsigned n);
  73. int    write(int fd, const char *buf, unsigned n);
  74. #else
  75. int    close();
  76. long    lseek();
  77. int    open();
  78. int    read();
  79. int    write();
  80. #endif    /* #ifdef AC_PROTO */
  81. #define MODE    (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
  82.                 /* file permissions for new files */
  83. #elif OPSYS == OS_VMS        /* VMS =======================================*/
  84.  
  85. #endif    /* #if OPSYS == OS_AMIGADOS */
  86.  
  87. /*man---------------------------------------------------------------------------
  88. NAME
  89.      b_uclose - unbuffered close block file
  90.  
  91. SYNOPSIS
  92.      #include "blkio_.h"
  93.  
  94.      int b_uclose(bp)
  95.      BLKFILE *bp;
  96.  
  97. DESCRIPTION
  98.      The b_uclose function closes the file associated with the BLKFILE
  99.      pointer bp.
  100.  
  101.      b_uclose will fail if one or more of the following is true:
  102.  
  103.      [EINVAL]       bp is not a valid BLKFILE pointer.
  104.      [BENOPEN]      bp is not open.
  105.  
  106. SEE ALSO
  107.      b_uopen.
  108.  
  109. DIAGNOSTICS
  110.      Upon successful completion, a value of 0 is returned.  Otherwise,
  111.      a value of -1 is returned, and errno set to indicate the error.
  112.  
  113. ------------------------------------------------------------------------------*/
  114. #ifdef AC_PROTO
  115. int b_uclose(BLKFILE *bp)
  116. #else
  117. int b_uclose(bp)
  118. BLKFILE *bp;
  119. #endif
  120. {
  121. #ifdef DEBUG
  122.     /* validate arguments */
  123.     if (!b_valid(bp)) {
  124.         BEPRINT;
  125.         errno = EINVAL;
  126.         return -1;
  127.     }
  128.  
  129.     /* check if not open */
  130.     if (!(bp->flags & BIOOPEN)) {
  131.         BEPRINT;
  132.         errno = BENOPEN;
  133.         return -1;
  134.     }
  135. #endif
  136.     /* close file */
  137. #if OPSYS == OS_AMIGADOS
  138.  
  139. #elif OPSYS == OS_DOS || OPSYS == OS_UNIX
  140.     if (close(bp->fd.i) == -1) {
  141.         BEPRINT;
  142.         return -1;
  143.     }
  144. #elif OPSYS == OS_MAC
  145.  
  146. #elif OPSYS == OS_VMS
  147.  
  148. #endif
  149.  
  150.     return 0;
  151. }
  152.  
  153. /*man---------------------------------------------------------------------------
  154. NAME
  155.      b_uendblk - unbuffered find end block
  156.  
  157. SYNOPSIS
  158.      #include "blkio_.h"
  159.  
  160.      int b_uendblk(bp, endblkp)
  161.      BLKFILE *bp;
  162.      bpos_t *endblkp;
  163.  
  164. DESCRIPTION
  165.      The b_uendblk function finds the block number of the first block
  166.      past the end of file of the file associated with BLKFILE pointer
  167.      bp.  This value is returned in the storage location pointed to by
  168.      endblkp.  Blocks in buffer storage and not yet written to the
  169.      file are not counted, so this function should normally be used
  170.      when the file is first opened or preceded by a call to bsync.
  171.  
  172.      If the file does not end on a block boundary, the result is the
  173.      same as if the partial block (or header) at the end of the file
  174.      did not exist.
  175.  
  176.      b_uendblk will fail if one or more of the following is true:
  177.  
  178.      [EINVAL]       bp is not a valid BLKFILE pointer.
  179.      [BENOPEN]      bp is not open.
  180.  
  181. DIAGNOSTICS
  182.      Upon successful completion, a value of 0 is returned.  Otherwise,
  183.      a value of -1 is returned, and errno set to indicate the error.
  184.  
  185. ------------------------------------------------------------------------------*/
  186. #ifdef AC_PROTO
  187. int b_uendblk(BLKFILE *bp, bpos_t *endblkp)
  188. #else
  189. int b_uendblk(bp, endblkp)
  190. BLKFILE *bp;
  191. bpos_t *endblkp;
  192. #endif
  193. {
  194. #if OPSYS == OS_AMIGADOS
  195.  
  196. #elif OPSYS == OS_DOS || OPSYS == OS_UNIX
  197.     long    pos    = 0;
  198. #elif OPSYS == OS_MAC
  199.  
  200. #elif OPSYS == OS_VMS
  201.  
  202. #endif
  203.  
  204. #ifdef DEBUG
  205.     /* validate arguments */
  206.     if (!b_valid(bp)) {
  207.         BEPRINT;
  208.         errno = EINVAL;
  209.         return -1;
  210.     }
  211.  
  212.     /* check if not open */
  213.     if (!(bp->flags & BIOOPEN)) {
  214.         BEPRINT;
  215.         errno = BENOPEN;
  216.         return -1;
  217.     }
  218. #endif
  219.  
  220. #if OPSYS == OS_AMIGADOS
  221.  
  222. #elif OPSYS == OS_DOS || OPSYS == OS_UNIX
  223.     /* find position of end of file */
  224.     pos = lseek(bp->fd.i, (long)0, SEEK_END);
  225.     if (pos == -1) {
  226.         BEPRINT;
  227.         return -1;
  228.     }
  229.  
  230.     /* check if empty file (or incomplete header) */
  231.     if (pos < bp->hdrsize) {
  232.         *endblkp = 0;
  233.         return 0;
  234.     }
  235.  
  236.     /* find length past end of header */
  237.     pos -= bp->hdrsize;
  238.  
  239.     /* set return argument */
  240.     *endblkp = (pos / bp->blksize) + 1;
  241. #elif OPSYS == OS_MAC
  242.  
  243. #elif OPSYS == OS_VMS
  244.  
  245. #endif
  246.  
  247.     return 0;
  248. }
  249.  
  250. /*man---------------------------------------------------------------------------
  251. NAME
  252.      b_ugetf - unbuffered get field from block file
  253.  
  254. SYNOPSIS
  255.      #include "blkio_.h"
  256.  
  257.      int b_ugetf(bp, bn, offset, buf, bufsize)
  258.      BLKFILE *bp;
  259.      bpos_t bn;
  260.      size_t offset;
  261.      void *buf;
  262.      size_t bufsize;
  263.  
  264. DESCRIPTION
  265.      The b_ugetf function reads bufsize characters from block number
  266.      bn of the block file associated with BLKFILE pointer bp into the
  267.      buffer pointed to by buf.  A value of 0 for bn indicates the file
  268.      header.  The read starts offset characters from the beginning of
  269.      the block.  The sum of the offset and the bufsize must not exceed
  270.      the header size if bn is equal to zero, or the block size if bn
  271.      is not equal to zero.
  272.  
  273.      b_ugetf will fail if one or more of the following is true:
  274.  
  275.      [EINVAL]       bp is not a valid BLKFILE pointer.
  276.      [EINVAL]       buf is NULL.
  277.      [EINVAL]       bufsize is less than 1.
  278.      [BEBOUND]      offset + bufsize extends across a block
  279.                     boundary.
  280.      [BEEOF]        Block bn is past the end of file.
  281.      [BEEOF]        End of file encountered within block bn.
  282.      [BENOPEN]      bp is not open.
  283.  
  284. SEE ALSO
  285.      b_uputf.
  286.  
  287. DIAGNOSTICS
  288.      Upon successful completion, a value of 0 is returned.  Otherwise,
  289.      a value of -1 is returned, and errno set to indicate the error.
  290.  
  291. ------------------------------------------------------------------------------*/
  292. #ifdef AC_PROTO
  293. int b_ugetf(BLKFILE *bp, bpos_t bn, size_t offset, void *buf, size_t bufsize)
  294. #else
  295. int b_ugetf(bp, bn, offset, buf, bufsize)
  296. BLKFILE *bp;
  297. bpos_t bn;
  298. size_t offset;
  299. void *buf;
  300. size_t bufsize;
  301. #endif
  302. {
  303. #if OPSYS == OS_AMIGADOS
  304.  
  305.  
  306. #elif OPSYS == OS_DOS || OPSYS == OS_UNIX
  307.     int    nr    = 0;
  308.     long    pos    = 0;
  309. #elif OPSYS == OS_MAC
  310.  
  311. #elif OPSYS == OS_VMS
  312.  
  313. #endif
  314.  
  315. #ifdef DEBUG
  316.     /* validate arguments */
  317.     if (!b_valid(bp) || buf == NULL || bufsize < 1) {
  318.         BEPRINT;
  319.         errno = EINVAL;
  320.         return -1;
  321.     }
  322.  
  323.     /* check if not open */
  324.     if (!(bp->flags & BIOOPEN)) {
  325.         BEPRINT;
  326.         errno = BENOPEN;
  327.         return -1;
  328.     }
  329.  
  330.     /* check if block boundary is crossed */
  331.     if (bn == 0) {
  332.         if ((offset + bufsize) > bp->hdrsize) {
  333.             BEPRINT;
  334.             errno = BEBOUND;
  335.             return -1;
  336.         }
  337.     } else {
  338.         if ((offset + bufsize) > bp->blksize) {
  339.             BEPRINT;
  340.             errno = BEBOUND;
  341.             return -1;
  342.         }
  343.     }
  344. #endif
  345.  
  346. #if OPSYS == OS_AMIGADOS
  347.  
  348. #elif OPSYS == OS_DOS || OPSYS == OS_UNIX
  349.     /* read from file into buffer */
  350.     if (bn == 0) {            /* header */
  351.         pos = 0;
  352.     } else {            /* block */
  353.         pos = bp->hdrsize + (bn - 1) * bp->blksize;
  354.     }
  355.     pos += offset;
  356.     if (lseek(bp->fd.i, pos, SEEK_SET) == -1) {
  357.         BEPRINT;
  358.         return -1;
  359.     }
  360.     nr = read(bp->fd.i, buf, (unsigned)bufsize);
  361.     if (nr == -1) {
  362.         BEPRINT;
  363.         return -1;
  364.     }
  365.     if (nr != bufsize) {
  366.         BEPRINT;
  367.         errno = BEEOF;
  368.         return -1;
  369.     }
  370. #elif OPSYS == OS_MAC
  371.  
  372. #elif OPSYS == OS_VMS
  373.  
  374. #endif
  375.  
  376.     return 0;
  377. }
  378.  
  379. /*man---------------------------------------------------------------------------
  380. NAME
  381.      b_uopen - unbuffered open block file
  382.  
  383. SYNOPSIS
  384.      #include "blkio_.h"
  385.  
  386.      int b_uopen(bp, filename, type)
  387.      BLKFILE *bp;
  388.      const char *filename;
  389.      const char *type;
  390.  
  391. DESCRIPTION
  392.      The b_uopen function opens the physical file associated with the
  393.      BLKFILE pointer bp.
  394.  
  395.      b_uopen will fail if one or more of the following is true:
  396.  
  397.      [EINVAL]       bp is not a valid BLKFILE pointer.
  398.      [EINVAL]       filename or type is the NULL pointer.
  399.  
  400. SEE ALSO
  401.      b_uclose.
  402.  
  403. DIAGNOSTICS
  404.      Upon successful completion, a value of 0 is returned.  Otherwise,
  405.      a value of -1 is returned, and errno set to indicate the error.
  406.  
  407. ------------------------------------------------------------------------------*/
  408. #ifdef AC_PROTO
  409. int b_uopen(BLKFILE *bp, const char *filename, const char *type)
  410. #else
  411. int b_uopen(bp, filename, type)
  412. BLKFILE *bp;
  413. const char *filename;
  414. const char *type;
  415. #endif
  416. {
  417. #if OPSYS == OS_AMIGADOS
  418.  
  419. #elif OPSYS == OS_DOS || OPSYS == OS_UNIX
  420.     int    fd    = 0;
  421.     int    oflag    = 0;
  422. #elif OPSYS == OS_MAC
  423.  
  424. #elif OPSYS == OS_VMS
  425.  
  426. #endif
  427.  
  428. #ifdef DEBUG
  429.     /* validate arguments */
  430.     if (!b_valid(bp) || filename == NULL || type == NULL) {
  431.         BEPRINT;
  432.         errno = EINVAL;
  433.         return -1;
  434.     }
  435. #endif
  436.     /* open file */
  437. #if OPSYS == OS_AMIGADOS
  438.  
  439. #elif OPSYS == OS_DOS
  440.     oflag = O_BINARY;
  441.     if (strcmp(type, BF_READ) == 0) {
  442.         oflag |= O_RDONLY;
  443.     } else if (strcmp(type, BF_RDWR) == 0) {
  444.         oflag |= O_RDWR;
  445.     } else if (strcmp(type, BF_CREATE) == 0) {
  446.         oflag |= O_RDWR | O_CREAT | O_EXCL;
  447.     } else if (strcmp(type, BF_CRTR) == 0) {
  448.         oflag |= O_RDWR | O_CREAT | O_TRUNC;
  449.     } else {
  450.         errno = EINVAL;
  451.         return -1;
  452.     }
  453.     fd = sopen(filename, oflag, SH_DENYNO, MODE);
  454.     if (fd == -1) {
  455. #ifdef DEBUG
  456.         if (errno != EACCES && errno != EEXIST && errno != ENOENT) BEPRINT;
  457. #endif
  458.         return -1;
  459.     }
  460.     bp->fd.i = fd;
  461. #elif OPSYS == OS_UNIX
  462.     oflag = 0;
  463.     if (strcmp(type, BF_READ) == 0) {
  464.         oflag |= O_RDONLY;
  465.     } else if (strcmp(type, BF_RDWR) == 0) {
  466.         oflag |= O_RDWR;
  467.     } else if (strcmp(type, BF_CREATE) == 0) {
  468.         oflag |= O_RDWR | O_CREAT | O_EXCL;
  469.     } else if (strcmp(type, BF_CRTR) == 0) {
  470.         oflag |= O_RDWR | O_CREAT | O_TRUNC;
  471.     } else {
  472.         errno = EINVAL;
  473.         return -1;
  474.     }
  475.     fd = open(filename, oflag, MODE);
  476.     if (fd == -1) {
  477. #ifdef DEBUG
  478.         if (errno != EACCES && errno != EEXIST && errno != ENOENT) BEPRINT;
  479. #endif
  480.         return -1;
  481.     }
  482.     bp->fd.i = fd;
  483. #elif OPSYS == OS_VMS
  484.  
  485. #endif
  486.  
  487.     return 0;
  488. }
  489.  
  490. /*man---------------------------------------------------------------------------
  491. NAME
  492.      b_uputf - unbuffered put field to block file
  493.  
  494. SYNOPSIS
  495.      #include "blkio_.h"
  496.  
  497.      int b_uputf(bp, bn, offset, buf, bufsize)
  498.      BLKFILE *bp;
  499.      bpos_t bn;
  500.      size_t offset;
  501.      const void *buf;
  502.      size_t bufsize;
  503.  
  504. DESCRIPTION
  505.      The b_uputf function writes bufsize characters from the buffer
  506.      pointed to by buf to block number bn of the block file associated
  507.      with BLKFILE pointer bp.  A value of zero for bn indicates the
  508.      file header.  The write starts offset characters from the
  509.      beginning of the block.  The sum of offset bufsize must not
  510.      exceed the header size if bn is equal to zero, or the block size
  511.      if bn is not equal to zero.
  512.  
  513.      b_uputf will fail if one or more of the following is true:
  514.  
  515.      [EINVAL]       bp is not a valid BLKFILE pointer.
  516.      [EINVAL]       buf is the NULL pointer.
  517.      [EINVAL]       bufsize is less than 1.
  518.      [BEBOUND]      offset + bufsize extends beyond the block
  519.                     boundary.
  520.      [BEEOF]        Partial block being written and block bn
  521.                     is past the end of file.
  522.      [BEEOF]        Complete block being written and block bn
  523.                     is more than 1 past the end of file.
  524.      [BENOPEN]      bp is not open for writing.
  525.  
  526. SEE ALSO
  527.      b_ugetf.
  528.  
  529. DIAGNOSTICS
  530.      Upon successful completion, a value of 0 is returned.  Otherwise,
  531.      a value of -1 is returned, and errno set to indicate the error.
  532.  
  533. ------------------------------------------------------------------------------*/
  534. #ifdef AC_PROTO
  535. int b_uputf(BLKFILE *bp, bpos_t bn, size_t offset, const void *buf, size_t bufsize)
  536. #else
  537. int b_uputf(bp, bn, offset, buf, bufsize)
  538. BLKFILE *bp;
  539. bpos_t bn;
  540. size_t offset;
  541. const void *buf;
  542. size_t bufsize;
  543. #endif
  544. {
  545. #if OPSYS == OS_AMIGADOS
  546.  
  547. #elif OPSYS == OS_DOS || OPSYS == OS_UNIX
  548.     int    nw    = 0;
  549.     long    pos    = 0;
  550. #elif OPSYS == OS_MAC
  551.  
  552. #elif OPSYS == OS_VMS
  553.  
  554. #endif
  555.  
  556. #ifdef DEBUG
  557.     /* validate arguments */
  558.     if (!b_valid(bp) || buf == NULL || bufsize < 1) {
  559.         BEPRINT;
  560.         errno = EINVAL;
  561.         return -1;
  562.     }
  563.  
  564.     /* check if not open */
  565.     if (!(bp->flags & BIOWRITE)) {
  566.         BEPRINT;
  567.         errno = BENOPEN;
  568.         return -1;
  569.     }
  570.  
  571.     /* check if block boundary is crossed */
  572.     if (bn == 0) {
  573.         if ((offset + bufsize) > bp->hdrsize) {
  574.             BEPRINT;
  575.             errno = BEBOUND;
  576.             return -1;
  577.         }
  578.     } else {
  579.         if ((offset + bufsize) > bp->blksize) {
  580.             BEPRINT;
  581.             errno = BEBOUND;
  582.             return -1;
  583.         }
  584.     }
  585. #endif
  586.  
  587. #if OPSYS == OS_AMIGADOS
  588.  
  589. #elif OPSYS == OS_DOS || OPSYS == OS_UNIX
  590.     /* write buffer to file */
  591.     if (bn == 0) {            /* header */
  592.         pos = 0;
  593.     } else {            /* block */
  594.         pos = bp->hdrsize + (bn - 1) * bp->blksize;
  595.     }
  596.     pos += offset;
  597.     if (lseek(bp->fd.i, pos, SEEK_SET) == -1) {
  598.         BEPRINT;
  599.         return -1;
  600.     }
  601.     nw = write(bp->fd.i, (char *)buf, (unsigned)bufsize);
  602.     if (nw == -1) {
  603.         BEPRINT;
  604.         return -1;
  605.     }
  606.     if (nw != bufsize) {
  607.         BEPRINT;
  608.         /* call write again to set errno (EFBIG or ENOSPC) */
  609.         nw = write(bp->fd.i, (char *)buf, (unsigned)1);
  610.         if (nw != -1) {
  611.             BEPRINT;
  612.             errno = BEPANIC;
  613.         }
  614.         return -1;
  615.     }
  616. #elif OPSYS == OS_MAC
  617.  
  618. #elif OPSYS == OS_VMS
  619.  
  620. #endif
  621.  
  622.     return 0;
  623. }
  624.